//! 告警管理模块
//! 
//! 提供告警规则定义、触发和通知功能

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;
use anyhow::{Result, anyhow};
use tracing::{debug, info, warn, error};
use uuid::Uuid;

use crate::{AlertConfig, EmailConfig};

/// 告警级别
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum AlertLevel {
    /// 信息
    Info,
    /// 警告
    Warning,
    /// 错误
    Error,
    /// 严重
    Critical,
}

impl AlertLevel {
    /// 转换为字符串
    pub fn as_str(&self) -> &'static str {
        match self {
            AlertLevel::Info => "info",
            AlertLevel::Warning => "warning",
            AlertLevel::Error => "error",
            AlertLevel::Critical => "critical",
        }
    }

    /// 从字符串解析
    pub fn from_str(s: &str) -> Result<Self> {
        match s.to_lowercase().as_str() {
            "info" => Ok(AlertLevel::Info),
            "warning" | "warn" => Ok(AlertLevel::Warning),
            "error" => Ok(AlertLevel::Error),
            "critical" | "crit" => Ok(AlertLevel::Critical),
            _ => Err(anyhow!("无效的告警级别: {}", s)),
        }
    }
}

/// 告警状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum AlertStatus {
    /// 触发中
    Firing,
    /// 已解决
    Resolved,
    /// 已确认
    Acknowledged,
    /// 已静默
    Silenced,
}

/// 告警规则
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AlertRule {
    /// 规则ID
    pub id: String,
    /// 规则名称
    pub name: String,
    /// 描述
    pub description: Option<String>,
    /// 告警级别
    pub level: AlertLevel,
    /// 条件表达式
    pub condition: String,
    /// 持续时间（秒）
    pub duration: u64,
    /// 标签
    pub labels: HashMap<String, String>,
    /// 注解
    pub annotations: HashMap<String, String>,
    /// 是否启用
    pub enabled: bool,
}

impl AlertRule {
    /// 创建新的告警规则
    pub fn new(name: String, level: AlertLevel, condition: String) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            name,
            description: None,
            level,
            condition,
            duration: 60, // 默认1分钟
            labels: HashMap::new(),
            annotations: HashMap::new(),
            enabled: true,
        }
    }

    /// 设置描述
    pub fn with_description(mut self, description: String) -> Self {
        self.description = Some(description);
        self
    }

    /// 设置持续时间
    pub fn with_duration(mut self, duration: u64) -> Self {
        self.duration = duration;
        self
    }

    /// 添加标签
    pub fn with_label(mut self, key: String, value: String) -> Self {
        self.labels.insert(key, value);
        self
    }

    /// 添加注解
    pub fn with_annotation(mut self, key: String, value: String) -> Self {
        self.annotations.insert(key, value);
        self
    }

    /// 检查条件是否满足（简化实现）
    pub fn evaluate(&self, _metrics: &HashMap<String, f64>) -> bool {
        // 这里应该实现真正的条件评估逻辑
        // 目前返回false作为占位符
        false
    }
}

/// 告警实例
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Alert {
    /// 告警ID
    pub id: String,
    /// 规则ID
    pub rule_id: String,
    /// 告警名称
    pub name: String,
    /// 告警级别
    pub level: AlertLevel,
    /// 告警状态
    pub status: AlertStatus,
    /// 告警消息
    pub message: String,
    /// 标签
    pub labels: HashMap<String, String>,
    /// 注解
    pub annotations: HashMap<String, String>,
    /// 触发时间
    pub fired_at: u64,
    /// 解决时间
    pub resolved_at: Option<u64>,
    /// 确认时间
    pub acknowledged_at: Option<u64>,
    /// 确认人
    pub acknowledged_by: Option<String>,
}

impl Alert {
    /// 创建新的告警
    pub fn new(rule: &AlertRule, message: String) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            rule_id: rule.id.clone(),
            name: rule.name.clone(),
            level: rule.level.clone(),
            status: AlertStatus::Firing,
            message,
            labels: rule.labels.clone(),
            annotations: rule.annotations.clone(),
            fired_at: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs(),
            resolved_at: None,
            acknowledged_at: None,
            acknowledged_by: None,
        }
    }

    /// 解决告警
    pub fn resolve(&mut self) {
        self.status = AlertStatus::Resolved;
        self.resolved_at = Some(
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        );
    }

    /// 确认告警
    pub fn acknowledge(&mut self, by: String) {
        self.status = AlertStatus::Acknowledged;
        self.acknowledged_at = Some(
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        );
        self.acknowledged_by = Some(by);
    }

    /// 静默告警
    pub fn silence(&mut self) {
        self.status = AlertStatus::Silenced;
    }

    /// 检查是否正在触发
    pub fn is_firing(&self) -> bool {
        self.status == AlertStatus::Firing
    }

    /// 获取持续时间（秒）
    pub fn duration(&self) -> u64 {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs();
        
        match self.status {
            AlertStatus::Resolved => {
                self.resolved_at.unwrap_or(now) - self.fired_at
            }
            _ => now - self.fired_at,
        }
    }
}

/// 告警通知器trait
#[async_trait::async_trait]
pub trait AlertNotifier: Send + Sync {
    /// 发送告警通知
    async fn notify(&self, alert: &Alert) -> Result<()>;
    
    /// 获取通知器名称
    fn name(&self) -> &str;
}

/// Webhook通知器
pub struct WebhookNotifier {
    name: String,
    url: String,
    client: reqwest::Client,
}

impl WebhookNotifier {
    pub fn new(name: String, url: String) -> Self {
        Self {
            name,
            url,
            client: reqwest::Client::new(),
        }
    }
}

#[async_trait::async_trait]
impl AlertNotifier for WebhookNotifier {
    async fn notify(&self, alert: &Alert) -> Result<()> {
        let payload = serde_json::json!({
            "alert_id": alert.id,
            "name": alert.name,
            "level": alert.level.as_str(),
            "status": alert.status,
            "message": alert.message,
            "labels": alert.labels,
            "annotations": alert.annotations,
            "fired_at": alert.fired_at,
        });

        let response = self.client
            .post(&self.url)
            .json(&payload)
            .send()
            .await?;

        if response.status().is_success() {
            debug!("Webhook通知发送成功: {}", alert.id);
            Ok(())
        } else {
            Err(anyhow!("Webhook通知发送失败: {}", response.status()))
        }
    }

    fn name(&self) -> &str {
        &self.name
    }
}

/// 日志通知器
pub struct LogNotifier {
    name: String,
}

impl LogNotifier {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

#[async_trait::async_trait]
impl AlertNotifier for LogNotifier {
    async fn notify(&self, alert: &Alert) -> Result<()> {
        match alert.level {
            AlertLevel::Info => info!("告警: {} - {}", alert.name, alert.message),
            AlertLevel::Warning => warn!("告警: {} - {}", alert.name, alert.message),
            AlertLevel::Error => error!("告警: {} - {}", alert.name, alert.message),
            AlertLevel::Critical => error!("严重告警: {} - {}", alert.name, alert.message),
        }
        Ok(())
    }

    fn name(&self) -> &str {
        &self.name
    }
}

/// 告警管理器
pub struct AlertManager {
    /// 配置
    config: AlertConfig,
    /// 告警规则
    rules: Arc<RwLock<HashMap<String, AlertRule>>>,
    /// 活跃告警
    alerts: Arc<RwLock<HashMap<String, Alert>>>,
    /// 通知器
    notifiers: Arc<RwLock<Vec<Arc<dyn AlertNotifier>>>>,
}

impl AlertManager {
    /// 创建新的告警管理器
    pub async fn new(config: AlertConfig) -> Result<Self> {
        let mut manager = Self {
            config,
            rules: Arc::new(RwLock::new(HashMap::new())),
            alerts: Arc::new(RwLock::new(HashMap::new())),
            notifiers: Arc::new(RwLock::new(Vec::new())),
        };

        // 初始化通知器
        manager.initialize_notifiers().await?;

        Ok(manager)
    }

    /// 初始化通知器
    async fn initialize_notifiers(&mut self) -> Result<()> {
        let mut notifiers = self.notifiers.write().await;

        // 添加日志通知器
        notifiers.push(Arc::new(LogNotifier::new("log".to_string())));

        // 添加Webhook通知器
        if let Some(webhook_url) = &self.config.webhook_url {
            notifiers.push(Arc::new(WebhookNotifier::new(
                "webhook".to_string(),
                webhook_url.clone(),
            )));
        }

        info!("初始化了 {} 个告警通知器", notifiers.len());
        Ok(())
    }

    /// 添加告警规则
    pub async fn add_rule(&self, rule: AlertRule) -> Result<()> {
        let mut rules = self.rules.write().await;
        let rule_id = rule.id.clone();
        rules.insert(rule_id.clone(), rule);
        info!("添加告警规则: {}", rule_id);
        Ok(())
    }

    /// 移除告警规则
    pub async fn remove_rule(&self, rule_id: &str) -> Result<()> {
        let mut rules = self.rules.write().await;
        rules.remove(rule_id);
        info!("移除告警规则: {}", rule_id);
        Ok(())
    }

    /// 触发告警
    pub async fn trigger_alert(&self, alert: Alert) -> Result<()> {
        let alert_id = alert.id.clone();
        
        // 存储告警
        {
            let mut alerts = self.alerts.write().await;
            alerts.insert(alert_id.clone(), alert.clone());
        }

        // 发送通知
        self.send_notifications(&alert).await?;

        info!("触发告警: {} - {}", alert.name, alert.message);
        Ok(())
    }

    /// 解决告警
    pub async fn resolve_alert(&self, alert_id: &str) -> Result<()> {
        let mut alerts = self.alerts.write().await;
        if let Some(alert) = alerts.get_mut(alert_id) {
            alert.resolve();
            info!("解决告警: {}", alert_id);
        }
        Ok(())
    }

    /// 确认告警
    pub async fn acknowledge_alert(&self, alert_id: &str, by: String) -> Result<()> {
        let mut alerts = self.alerts.write().await;
        if let Some(alert) = alerts.get_mut(alert_id) {
            alert.acknowledge(by.clone());
            info!("确认告警: {} by {}", alert_id, by);
        }
        Ok(())
    }

    /// 获取活跃告警
    pub async fn get_active_alerts(&self) -> Result<Vec<Alert>> {
        let alerts = self.alerts.read().await;
        Ok(alerts
            .values()
            .filter(|alert| alert.is_firing())
            .cloned()
            .collect())
    }

    /// 获取所有告警
    pub async fn get_all_alerts(&self) -> Result<Vec<Alert>> {
        let alerts = self.alerts.read().await;
        Ok(alerts.values().cloned().collect())
    }

    /// 发送通知
    async fn send_notifications(&self, alert: &Alert) -> Result<()> {
        let notifiers = self.notifiers.read().await;
        
        for notifier in notifiers.iter() {
            if let Err(e) = notifier.notify(alert).await {
                error!("通知发送失败 [{}]: {}", notifier.name(), e);
            }
        }

        Ok(())
    }

    /// 获取告警统计
    pub async fn get_alert_stats(&self) -> Result<serde_json::Value> {
        let alerts = self.alerts.read().await;
        let rules = self.rules.read().await;

        let mut stats_by_level = HashMap::new();
        let mut stats_by_status = HashMap::new();

        for alert in alerts.values() {
            *stats_by_level.entry(alert.level.as_str()).or_insert(0) += 1;
            *stats_by_status.entry(&alert.status).or_insert(0) += 1;
        }

        Ok(serde_json::json!({
            "total_rules": rules.len(),
            "total_alerts": alerts.len(),
            "active_alerts": alerts.values().filter(|a| a.is_firing()).count(),
            "stats_by_level": stats_by_level,
            "stats_by_status": stats_by_status,
        }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_alert_level_conversion() {
        assert_eq!(AlertLevel::Info.as_str(), "info");
        assert_eq!(AlertLevel::Warning.as_str(), "warning");
        assert_eq!(AlertLevel::Error.as_str(), "error");
        assert_eq!(AlertLevel::Critical.as_str(), "critical");

        assert_eq!(AlertLevel::from_str("info").unwrap(), AlertLevel::Info);
        assert_eq!(AlertLevel::from_str("warning").unwrap(), AlertLevel::Warning);
        assert_eq!(AlertLevel::from_str("error").unwrap(), AlertLevel::Error);
        assert_eq!(AlertLevel::from_str("critical").unwrap(), AlertLevel::Critical);
    }

    #[test]
    fn test_alert_rule_creation() {
        let rule = AlertRule::new(
            "high_cpu".to_string(),
            AlertLevel::Warning,
            "cpu_usage > 80".to_string(),
        )
        .with_description("CPU使用率过高".to_string())
        .with_duration(300)
        .with_label("service".to_string(), "api".to_string());

        assert_eq!(rule.name, "high_cpu");
        assert_eq!(rule.level, AlertLevel::Warning);
        assert_eq!(rule.condition, "cpu_usage > 80");
        assert_eq!(rule.duration, 300);
        assert_eq!(rule.labels.get("service"), Some(&"api".to_string()));
    }

    #[test]
    fn test_alert_lifecycle() {
        let rule = AlertRule::new(
            "test_rule".to_string(),
            AlertLevel::Error,
            "test_condition".to_string(),
        );

        let mut alert = Alert::new(&rule, "测试告警".to_string());
        assert!(alert.is_firing());
        assert_eq!(alert.status, AlertStatus::Firing);

        alert.acknowledge("admin".to_string());
        assert_eq!(alert.status, AlertStatus::Acknowledged);
        assert_eq!(alert.acknowledged_by, Some("admin".to_string()));

        alert.resolve();
        assert_eq!(alert.status, AlertStatus::Resolved);
        assert!(!alert.is_firing());
    }

    #[tokio::test]
    async fn test_alert_manager() {
        let config = AlertConfig {
            enabled: true,
            rules_file: None,
            webhook_url: None,
            email_config: None,
        };

        let manager = AlertManager::new(config).await.unwrap();

        // 添加规则
        let rule = AlertRule::new(
            "test_rule".to_string(),
            AlertLevel::Warning,
            "test > 10".to_string(),
        );
        let rule_id = rule.id.clone();
        manager.add_rule(rule.clone()).await.unwrap();

        // 触发告警
        let alert = Alert::new(&rule, "测试告警消息".to_string());
        let alert_id = alert.id.clone();
        manager.trigger_alert(alert).await.unwrap();

        // 检查活跃告警
        let active_alerts = manager.get_active_alerts().await.unwrap();
        assert_eq!(active_alerts.len(), 1);
        assert_eq!(active_alerts[0].id, alert_id);

        // 确认告警
        manager.acknowledge_alert(&alert_id, "test_user".to_string()).await.unwrap();

        // 解决告警
        manager.resolve_alert(&alert_id).await.unwrap();

        // 获取统计信息
        let stats = manager.get_alert_stats().await.unwrap();
        assert_eq!(stats["total_alerts"].as_u64().unwrap(), 1);
    }
}
